/**
 * Project Name:fire-industry-DM-center
 * File Name:JWTLoginFilter.java
 * Package Name:com.firestone.config.filter
 * Date:2018年3月22日上午10:19:50
 *
*/

package com.firestone.config.jwt;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.firestone.bean.dto.user.User;
import com.firestone.core.constants.ConstantKey;
import com.firestone.core.utils.HttpResponseUtil;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

/**
 * @Description: TODO( 验证用户名密码正确后，生成一个token，并将token返回给客户端
 *               该类继承自UsernamePasswordAuthenticationFilter，重写了其中的2个方法
 *               attemptAuthentication ：接收并解析用户凭证。 successfulAuthentication
 *               ：用户成功登录后，这个方法会被调用，我们在这个方法里生成token。)
 * @author CAIYJ
 * @date 2018年3月22日 上午10:19:50
 */
public class JWTLoginFilter extends UsernamePasswordAuthenticationFilter {
    private AuthenticationManager authenticationManager;

    public JWTLoginFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    // 接收并解析用户凭证
    @Override
    public Authentication attemptAuthentication(HttpServletRequest req,
            HttpServletResponse res) throws AuthenticationException {
        Authentication authentication = null;
        try {
            try {
                User user = new ObjectMapper().readValue(req.getInputStream(),
                        User.class);
                authentication = authenticationManager
                        .authenticate(new UsernamePasswordAuthenticationToken(
                                user.getUsername(), user.getPassword(),
                                new ArrayList<>()));
            } catch (AuthenticationException e) {
                HttpResponseUtil.noUser(res);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return authentication;
    }

    // 用户成功登录后，这个方法会被调用，我们在这个方法里生成token
    @Override
    protected void successfulAuthentication(HttpServletRequest req,
            HttpServletResponse res, FilterChain chain, Authentication auth)
                    throws IOException, ServletException {
        String token = Jwts.builder().setSubject(auth.getName())
                .setExpiration(new Date(
                        System.currentTimeMillis() + 60 * 60 * 24 * 1000))
                .signWith(SignatureAlgorithm.HS512, ConstantKey.SIGNING_KEY) // 采用什么算法是可以自己选择的，不一定非要采用HS512
                .compact();
        res.addHeader("token", "Firestone " + token);
    }
}
